import anime from 'animejs'
import { edgeConfig } from '../config/edgeConfig'
import { sizeConfig } from '../config/sizeConfig'
import { BoolType, IDataValue, IModuleWithState } from '../types'
import {
    createDataValue,
    getCenterPoint,
    setDomBoolVal,
    toBinaryStr,
} from '../utils'
import { bus1, bus2 } from './bus'

interface IMultiplexer21State {
    s0: BoolType
    value: number
}

interface IMultiplexer21 extends IModuleWithState<IMultiplexer21State> {
    dataItem: IDataValue<number> | null
    animation: () => Promise<void>
}

/**
 * multiplexer21 2-1多路复用器模块
 */
export const multiplexer21: IMultiplexer21 = {
    name: 'multiplexer21',
    dataItem: null,
    state: {
        s0: 1,
        value: -1,
    },
    async setState(prop, value) {
        if (this.state[prop] === value) return
        if (prop === 's0') {
            this.state[prop] = value
            setDomBoolVal(prop, this.state[prop] as BoolType)
        }
        this.change!()
        return
    },
    async change() {
        // 在数据变化时
        const m21BottomCenterPoint = getCenterPoint(
            sizeConfig.multiplexer21,
            'bottom'
        )
        // 从0号口读取数据，送到输出
        let data = bus2.getData()
        if (this.state.s0 === 0) {
            m21BottomCenterPoint.x -= sizeConfig.multiplexer21.width / 4 // 加上宽度的一半，减去箭头的宽度的一半
        } else {
            // 从1号口读取数据，送到输出
            m21BottomCenterPoint.x += sizeConfig.multiplexer21.width / 4 // 加上宽度的一半，减去箭头的宽度的一半
            data = bus1.getData()
        }
        if (this.state.value === data) return
        // 保存数据
        this.state.value = data
        const text = toBinaryStr(data)
        if (this.dataItem === null) {
            this.dataItem = createDataValue(data, text, m21BottomCenterPoint)
        }
        this.dataItem.setText(text)
        this.dataItem.setPosition(m21BottomCenterPoint)
        return this.animation()
    },
    async animation() {
        // 开始动画，先移动到中间，然后移动到输出
        const timeline = anime.timeline({
            targets: this.dataItem!.dom,
            easing: 'linear',
            duration: (edgeConfig.time.rise + edgeConfig.time.high) * 0.05,
        })
        const m21CenterPoint = getCenterPoint(sizeConfig.multiplexer21)
        const regBottomCenterPoint = getCenterPoint(sizeConfig.reg, 'bottom')
        timeline
            .add({
                translateX: m21CenterPoint.x,
                translateY: m21CenterPoint.y - 10,
            })
            .add({
                translateX: regBottomCenterPoint.x,
                translateY: regBottomCenterPoint.y,
            })
        return timeline.finished
    },
    init() {
        // 设置s0的初始值
        setDomBoolVal('s0', this.state.s0)
        this.change!()
    },
}
